package com.hundun.vision.biz.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.binance.connector.futures.client.impl.UMFuturesClientImpl;
import com.hundun.vision.biz.dto.CoinDTO;
import com.hundun.vision.biz.dto.PositionDTO;
import com.hundun.vision.biz.enums.OrderSide;
import com.hundun.vision.biz.enums.OrderType;
import com.hundun.vision.biz.enums.OrderValidityType;
import com.hundun.vision.biz.enums.OrderWorkingType;
import com.hundun.vision.biz.service.AccountService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.LinkedHashMap;
import java.util.List;

import static com.hundun.vision.biz.enums.OrderType.LIMIT;

/**
 * @author ：RuoChen
 * @date ：14:21 2024/11/28
 * @description：账户服务实现类
 */
@Service
@Slf4j
public class AccountServiceImpl implements AccountService {
    @Value("${binance.service_url}")
    private String serviceUrl;

    @Value("${binance.api_key}")
    private String apiKey;

    @Value("${binance.secret_key}")
    private String secretKey;

    @Override
    public Long getTimestamp() {
        UMFuturesClientImpl client = new UMFuturesClientImpl();
        String result = client.market().time();
        JSONObject data = JSONObject.parseObject(result);
        return data.getLong("serverTime");
    }

    @Override
    public BigDecimal getBalance(String asset) {
        BigDecimal balance = BigDecimal.ZERO;
        List<CoinDTO> coins;
        LinkedHashMap<String, Object> parameters = new LinkedHashMap<>();
        UMFuturesClientImpl client = new UMFuturesClientImpl(apiKey, secretKey, serviceUrl);
        String result = client.account().futuresAccountBalance(parameters);
        coins = JSON.parseArray(result, CoinDTO.class);
        CoinDTO coin = coins.stream().filter(item -> item.getAsset().equals(asset.toUpperCase())).findFirst().orElse(null);
        if (coin != null) {
            balance = coin.getAvailableBalance();
        }
        return balance;
    }

    @Override
    public PositionDTO getPosition(String symbol) {
        List<PositionDTO> positions;
        UMFuturesClientImpl client = new UMFuturesClientImpl(apiKey, secretKey, serviceUrl);
        LinkedHashMap<String, Object> parameters = new LinkedHashMap<>();
        parameters.put("timestamp", getTimestamp());
        String result = client.account().accountInformation(parameters);
        JSONObject data = JSONObject.parseObject(result);
        positions = JSON.parseArray(data.getString("positions"), PositionDTO.class);
        PositionDTO position = positions.stream().filter(item -> item.getSymbol().equals(symbol.toUpperCase())).findFirst().orElse(null);
        return position;
    }

    @Override
    public Boolean changeLeverage(String symbol, Integer leverage) {
        LinkedHashMap<String, Object> parameters = new LinkedHashMap<>();
        UMFuturesClientImpl client = new UMFuturesClientImpl(apiKey, secretKey, serviceUrl);
        parameters.put("symbol", symbol);
        parameters.put("leverage", leverage);
        parameters.put("timestamp", getTimestamp());
        String result = client.account().changeInitialLeverage(parameters);
        return true;
    }

    @Override
    public Boolean createOrder(String symbol, OrderSide orderSide, OrderType orderType,
                               OrderValidityType orderValidityType, OrderWorkingType orderWorkingType,
                               BigDecimal price, BigDecimal quantity) {
        if (orderSide == null) {
            return false;
        }
        UMFuturesClientImpl client = new UMFuturesClientImpl(apiKey, secretKey, serviceUrl);
        LinkedHashMap<String, Object> parameters = new LinkedHashMap<>();
        parameters.put("symbol", symbol.toUpperCase());
        parameters.put("side", orderSide.getSide());
        parameters.put("type", orderType.getType());
        if (LIMIT.equals(orderType)) {
            parameters.put("timeInForce", orderValidityType.getCode());
            parameters.put("price", price);
        }
        parameters.put("workingType", orderWorkingType.getCode());
        parameters.put("quantity", quantity);
        parameters.put("timestamp", getTimestamp());
        log.info("createOrder: {}", JSON.toJSONString(parameters));
        String result = client.account().newOrder(parameters);
        return true;
    }

    @Override
    public Boolean openOrder(String symbol) {
        UMFuturesClientImpl client = new UMFuturesClientImpl(apiKey, secretKey, serviceUrl);
        LinkedHashMap<String, Object> parameters = new LinkedHashMap<>();
        parameters.put("symbol", symbol.toUpperCase());
        parameters.put("timestamp", getTimestamp());
        String result = client.account().currentAllOpenOrders(parameters);
        JSONArray openOrders = JSON.parseArray(result);
        return !openOrders.isEmpty();
    }

    @Override
    public Boolean cancelAllOrders(String symbol) {
        UMFuturesClientImpl client = new UMFuturesClientImpl(apiKey, secretKey, serviceUrl);
        LinkedHashMap<String, Object> parameters = new LinkedHashMap<>();
        parameters.put("symbol", symbol);
        String result = client.account().cancelAllOpenOrders(parameters);
        return true;
    }
}
